<?php
declare (strict_types = 1);
namespace app\common\model\content;

use app\admin\traits\GetTableData;
use think\Model;
use app\common\model\user\User;

/**
 * @mixin think\Model
 */
class Tag extends Model
{
    use GetTableData;

    // 定义时间戳字段名
    protected $updateTime = false;

    // 设置字段信息
    protected $schema = [
        'id'            => 'int',
        'name'          => 'string',
        'user_id'       => 'int',
        'create_time'   => 'int',
    ];

    // 设置字段信息
    protected $type = [
        'id'            => 'integer',
        'user_id'       => 'integer',
    ];


    //插入之前完善数据
    public static function onBeforeInsert(Model $model)
    {
        $model->setAttr('user_id',app()->user->getId());
    }
    //关联用户
    public function user()
    {
        return $this->belongsTo(User::class,'user_id', 'id')->bind([
            'username' => 'showName',
            'avatar' => 'avatarUrl'
        ]);
    }

    //删除之后删除所有该标签的关联记录
    public static function onAfterDelete(Model $model)
    {
        ArticleTag::where(['tag_id'=>$model->id])->delete();
    }

    //关联文章
    public function articles()
    {
        return $this->belongsToMany(Article::class, ArticleTag::class);
    }


    //清空指定文章关联的标签记录(和失去关联的标签)
    public static function cleanTags(int $article_id){
        //关联过的标签
        $related_tags = ArticleTag::where(['article_id'=>$article_id])->column('tag_id');

        //如果没有关联过的标签
        if(!$related_tags){
            return true;
        }

        //删除该文章的关联记录
        ArticleTag::where(['article_id'=>$article_id])->delete();

        //获取没有失去关联的标签id
        $avail_tags = ArticleTag::where('tag_id', 'in', $related_tags)->column('tag_id');

        //删除失去关联的标签
        $clean_ids = array_values(array_diff($related_tags, $avail_tags));
        if (count($clean_ids) > 0) return static::destroy($clean_ids);
        return true;

    }

    /**
     * 新建标签 新建关联数据
     * @param string $tags
     * @param int $article_id
     * @return
     * @throws \Exception
     */
    public static function store(string $tags, int $article_id){
        //格式化标签
        $arr = explode(',', str_replace('，', ',', cutstr_html($tags)));

        //去除无效标签
        $tags_arr = [];
        foreach ($arr as $k => $item){
            if ( empty($item) ) continue;
            $tags_arr[] = strtolower($item);
        }
        $tags_arr = array_unique($tags_arr);
        if (empty($tags_arr)) return true;

        //保存标签
        $tags_id = static::saveTags($tags_arr);

        //保存关联数据
        static::saveRelateArticle($tags_id, $article_id);

        return true;
    }

    /**
     * 保存标签
     * @param array $arr
     * @return array
     * @throws \Exception
     */
    private static function saveTags(array $arr){
        if (empty($arr)) return [];

        //获取已经存在的标签
        $exist = static::where('name','in', $arr)->column('id','name');

        //构建标签批量插入数据
        $batch = [];
        foreach( $arr as $k => $v ){
            if (key_exists($v, $exist)){
                $batch[] = ['id'=> $exist[$v], 'name'=>$v];
            }else{
                $batch[] = ['name'=>$v];
            }
        }

        //保存到数据库
        return (new static())->saveAll($batch)->column('id');
    }

    /**
     * 保存文章和标签的关联数据
     * @param array $tags_id
     * @param int $article_id
     * @throws \Exception
     */
    private static function saveRelateArticle(array $tags_id, int $article_id){
        $data = [];
        foreach ($tags_id as $v){
            $data[] = [
                'article_id' => $article_id,
                'tag_id' => (int) $v
            ];
        }
        (new ArticleTag())->saveAll($data);
    }

    /**
     * 获取首页列表数据
     */
    public static function getListData(array $ruleWhere = []){
        //要查询的字段
        $fields = [
            'fields' =>['id','name','user_id','create_time'],
            'with' => ['user'],
            'withCount' => ['articles'],
        ];

        //(构建查询条件)
        $where = [];
        if ($start = input('start_time')){
            $where[] = ['create_time', '>=', strtotime($start)];
        }
        if ($end = input('end_time')){
            $where[] = ['create_time', '<=', strtotime($end)];
        }
        if ($name = input('name')){
            $where[] = ['name','like','%'.$name.'%'];
        }

        //排序
        $order = ['id'=>'desc','create_time'=>'desc'];

        //[count:查询到的数目, list:记录列表]
        $data = static::operateDatum($where, $fields, $order,$ruleWhere);

        return [
            'count' => $data['count'],
            'data' => $data['list']
        ];
    }

}
